package cn.okcode.api.framework;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ClassUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 分发器接口
 *
 * @author pyk13
 */
public interface IDispatcher {
    void doDispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException;
    void refresh();

    default String default2String(Object value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return value.toString();
    }

    default boolean default2Bool(Object value, boolean defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return Boolean.parseBoolean(value.toString());
    }

    default List<Object> findParameterValues(HttpServletRequest request, Map<String, Class<?>> parameterDefinitions) {
        List<Object> values = new ArrayList<>();
        for (Map.Entry<String, Class<?>> entry : parameterDefinitions.entrySet()) {
            Object value;
            if (ClassUtil.isSimpleValueType(entry.getValue())) {
                value = Convert.convert(entry.getValue(), request.getParameter(entry.getKey()));
            } else {
                value = JSON.parseObject(request.getParameter(entry.getKey()), entry.getValue());
            }
            values.add(value);
        }
        return values;
    }

    default Map<String, Class<?>> findParameterDefinitions(HttpServletRequest request) {
        Map<String, Class<?>> parameters = new LinkedHashMap<>();
        String defOfParameters = request.getParameter("_parameters");
        if (StringUtils.isBlank(defOfParameters)) {
            return parameters;
        }
        if (StringUtils.isNotBlank(defOfParameters)) {
            JSONArray jsonArray = JSON.parseArray(defOfParameters);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                Object oName = jsonObject.get("name");
                if (oName == null || StringUtils.isBlank(oName.toString())) {
                    throw new ActionException("参数格式不对：[" + defOfParameters + "]");
                }
                String name = oName.toString();
                String strParamType = default2String(jsonObject.get("type"), String.class.getName());

                Class<?> parameterType;
                switch (strParamType) {
                    case "byte":
                        parameterType = byte.class;
                        break;
                    case "short":
                        parameterType = short.class;
                        break;
                    case "int":
                        parameterType = int.class;
                        break;
                    case "long":
                        parameterType = long.class;
                        break;
                    case "float":
                        parameterType = float.class;
                        break;
                    case "double":
                        parameterType = double.class;
                        break;
                    case "char":
                        parameterType = char.class;
                        break;
                    case "boolean":
                        parameterType = boolean.class;
                        break;
                    default:
                        try {
                            parameterType = Class.forName(strParamType);
                        } catch (ClassNotFoundException e) {
                            throw new ActionException("错误的参数类型:[" + strParamType + "]");
                        }
                        break;
                }
                parameters.put(name, parameterType);
            }
        }
        return parameters;
    }
}
